package lightswitch.server.code.sqlhelper;

import java.util.List;


import lightswitch.server.code.sqlhelper.expression.Expression;
import lightswitch.server.code.sqlhelper.expression.SingleExpression;
import lightswitch.server.code.sqlhelper.expression.arithmetic.Addition;
import lightswitch.server.code.sqlhelper.expression.arithmetic.Division;
import lightswitch.server.code.sqlhelper.expression.arithmetic.Multiplication;
import lightswitch.server.code.sqlhelper.expression.arithmetic.Subtraction;
import lightswitch.server.code.sqlhelper.expression.operators.conditional.AndExpression;
import lightswitch.server.code.sqlhelper.expression.operators.conditional.OrExpression;
import lightswitch.server.code.sqlhelper.expression.operators.relational.AllExpression;
import lightswitch.server.code.sqlhelper.expression.operators.relational.Between;
import lightswitch.server.code.sqlhelper.expression.operators.relational.EqualsTo;
import lightswitch.server.code.sqlhelper.expression.operators.relational.ExistExpression;
import lightswitch.server.code.sqlhelper.expression.operators.relational.GreaterThan;
import lightswitch.server.code.sqlhelper.expression.operators.relational.GreaterThanEquals;
import lightswitch.server.code.sqlhelper.expression.operators.relational.InExpression;
import lightswitch.server.code.sqlhelper.expression.operators.relational.LikeExpression;
import lightswitch.server.code.sqlhelper.statement.select.From;
import lightswitch.server.code.util.StringHelper;

import lightswitch.server.code.util.TypeOfOperator;

public class ExpressionHelper {
	public static Expression parseExpression(String statement, From _from) {
		statement = StringHelper.NormalizeString(statement);

		List<String> strList = StringHelper.SplitStringInEqualLevel(statement);

		if (strList.size() == 1) {

			if (strList.get(0).matches("[0-9-]+")) {
				return new SingleExpression(strList.get(0));
			}

			if (strList.get(0).matches("[0-9-.]+")) {
				return new SingleExpression(strList.get(0));
			}

			if (strList.get(0).equals("true") || strList.get(0).equals("false") ||strList.get(0).equals("null")
					|| strList.get(0).matches("'.+'")
					|| strList.get(0).matches("`.+`"))
				return new SingleExpression(strList.get(0));

			if (strList.get(0).split("\\.").length == 2) {
				return new SingleExpression(strList.get(0));
			} else {
				if (strList.get(0).split("\\.").length == 1) {
					// xu ly
					if (_from._tableList.size() == 1) {
						String str = _from._tableList.get(0).alias + "."
								+ strList.get(0);
						return new SingleExpression(str);
					} else {
						// throw exception
						return null;
					}

				} else {
					// throw exception
					return null;
				}
			}

		}
		if (statement.contains(" and ") || statement.contains(" or ")) {
			for (int i = 0; i < strList.size(); i++) {
				if (strList.get(i).equals("and")) {
					String left = "";
					String right = "";
					for (int j = 0; j < i; j++) {
						left += strList.get(j);
						left += " ";
					}
					for (int j = i + 1; j < strList.size(); j++) {
						right += strList.get(j);
						right += " ";
					}
					return new AndExpression(left, right, true, _from);

				}
				if (strList.get(i).equals("or")) {
					String left = "";
					String right = "";
					for (int j = 0; j < i; j++) {
						left += strList.get(j);
						left += " ";
					}
					for (int j = i + 1; j < strList.size(); j++) {
						right += strList.get(j);
						right += " ";
					}
					return new OrExpression(left, right, true, _from);

				}
			}
		} else {
			if (statement.contains("=") || statement.contains("<>")
					|| statement.contains("!=") || statement.contains(">=")
					|| statement.contains("<=") || statement.contains(">")
					|| statement.contains("<") || statement.contains("like")
					|| statement.contains("between")
					|| statement.contains("notbetween")
					|| statement.contains("exist")
					|| statement.contains("notexist")
					|| statement.contains(" in ")
					|| statement.contains(" notin ")
					|| statement.contains("<>all")
					|| statement.contains("=all") || statement.contains("<all")
					|| statement.contains("<=all")
					|| statement.contains(">all")
					|| statement.contains(">=all")) {
				for (int i = 0; i < strList.size(); i++) {
					// //////////////////////////////
					if (strList.get(i).equals("=")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new EqualsTo(left, right, false, _from);

					}
					if (strList.get(i).equals("<>")
							|| strList.get(i).equals("!=")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}

						return new EqualsTo(left, right, true, _from);

					}
					if (strList.get(i).equals(">=")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new GreaterThanEquals(left, right, false, _from);

					}
					if (strList.get(i).equals(">")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new GreaterThan(left, right, false, _from);

					}
					if (strList.get(i).equals("<=")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new GreaterThanEquals(left, right, true, _from);

					}
					if (strList.get(i).equals("<")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new GreaterThan(left, right, true, _from);

					}
					if (strList.get(i).equals("like")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new LikeExpression(left, right, false, _from);
					}
					if (strList.get(i).equals("notlike")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new LikeExpression(left, right, true, _from);
					}
					if (strList.get(i).equals("between")) {
						String value = "";
						String from = "";
						String to = "";
						for (int j = 0; j < i; j++) {
							value += strList.get(j);
							value += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							if (strList.get(j).equals("to"))// xxx
							{
								for (int k = i + 1; k < j; k++) {
									from += strList.get(k);
									from += " ";
								}
								for (int k = j + 1; k < strList.size(); k++) {
									to += strList.get(k);
									to += " ";
								}
							}
						}
						return new Between(value, from, to, false, _from);

					}
					if (strList.get(i).equals("notbetween")) {
						String value = "";
						String from = "";
						String to = "";
						for (int j = 0; j < i; j++) {
							value += strList.get(j);
							value += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							if (strList.get(j).equals("to"))// xxx
							{
								for (int k = i + 1; k < j; k++) {
									from += strList.get(k);
									from += " ";
								}
								for (int k = j + 1; k < strList.size(); k++) {
									to += strList.get(k);
									to += " ";
								}
							}
						}
						return new Between(value, from, to, true, _from);

					}
					if (strList.get(i).equals("in")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new InExpression(left, right, false, _from);

					}
					if (strList.get(i).equals("notin")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new InExpression(left, right, true, _from);
					}
					if (strList.get(i).equals("<>all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.DIFFERENT, _from);
					}
					if (strList.get(i).equals("=all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.EQUAL, _from);
					}
					if (strList.get(i).equals(">=all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.GREATEROREQUAL, _from);
					}

					if (strList.get(i).equals(">all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.GREATER, _from);
					}
					if (strList.get(i).equals("<all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.LESS, _from);
					}
					if (strList.get(i).equals("<=all")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new AllExpression(left, right,
								TypeOfOperator.LESSOREQUAL, _from);
					}
					
					if (strList.get(i).equals("exist")) {
						String right = "";
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new ExistExpression( right,false, _from);
					}
					
					if (strList.get(i).equals("notexist")) {
						String right = "";
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						right = "`" + right + "`";
						return new ExistExpression( right,true, _from);
					}
					// //////////////////////////////
					// //////////////////////////
					// //////////////////////////////
				}

			} else {
				for (int i = 0; i < strList.size(); i++)

				{
					if (strList.get(i).equals("+")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new Addition(left, right, true, _from);

					}
					if (strList.get(i).equals("-\\s")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new Subtraction(left, right, true, _from);

					}
					if (strList.get(i).equals("*")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new Multiplication(left, right, true, _from);

					}
					if (strList.get(i).equals("/")) {
						String left = "";
						String right = "";
						for (int j = 0; j < i; j++) {
							left += strList.get(j);
							left += " ";
						}
						for (int j = i + 1; j < strList.size(); j++) {
							right += strList.get(j);
							right += " ";
						}
						return new Division(left, right, true, _from);

					}

				}
			}
		}
		// Expression result = new AndExpression("left", "right",true);

		return null;
	}

}
